package libretto.activity;

import java.io.IOException;
import java.net.ConnectException;
import java.util.HashMap;
import java.util.regex.Pattern;

import javax.security.auth.login.LoginException;

import libretto.connection.ConnectionManager;
import libretto.connection.Esse3HttpClient;
import libretto.utils.IDContextMenu;
import libretto.utils.Utils;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;

public class Login extends Activity implements OnClickListener {

	private static final int SUCCESS = 0;
	private static final int CONNECTION_ERROR = 1;
	private static final int LOGIN_ERROR = 2;
	private static final int IO_ERROR = 3;
	private static final int SHOW_DIALOG = 4;
	private static final int CONTEXT_MENU_ID = 5;
	private static final String PREFS_NAME = "Credentials";
	private static final String PREF_USERNAME = "username";
	private static final String PREF_PASSWORD = "password";
	private static final String PREF_REMEMBER = "remember";

	private ConnectionManager cm;
	private HashMap<String, String> html_pages;
	private Intent intent;

	private EditText uname;
	private EditText pword;
	private CheckBox remeb;
	private Button login_B;
	private ProgressDialog progressDialog;
	private IDContextMenu iconContextMenu;
	private AlertDialog builder;
	private String username;
	private String password;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.login);
		init();
	}

	private void init() {
		html_pages = new HashMap<String, String>();

		// initGUI
		uname = (EditText) findViewById(R.id.username);
		pword = (EditText) findViewById(R.id.password);
		remeb = (CheckBox) findViewById(R.id.id_remember_up);
		uname.addTextChangedListener(new InputValidator(uname));
		login_B = (Button) findViewById(R.id.login);
		login_B.setOnClickListener(this);
		builder = new AlertDialog.Builder(this).create();
		uname.setText((CharSequence) loadCredentials(PREF_USERNAME));
		pword.setText((CharSequence) loadCredentials(PREF_PASSWORD));
		remeb.setChecked((Boolean) loadCredentials(PREF_REMEMBER));
	}

	private void login() {
		Log.i("INFO", "Login:");
		uname = (EditText) findViewById(R.id.username);

		// user: id067723 pass: HXCHW specialistica
		// user: id072693 pass: Fulvio triennale

		username = uname.getText().toString();
		password = pword.getText().toString();

		saveCredentials(remeb.isChecked());

		cm = ConnectionManager.getInstance();

		try {
			cm.authenticate(username, password);
			initPage(Utils.target_libretto);
		} catch (ConnectException e) {
			Message msg = new Message();
			msg.obj = e.getMessage();
			msg.what = CONNECTION_ERROR;
			loginHandler.sendMessage(msg);
		} catch (LoginException e) {
			Message msg = new Message();
			msg.obj = e.getMessage();
			msg.what = LOGIN_ERROR;
			loginHandler.sendMessage(msg);
		} catch (IOException e) {
			Message msg = new Message();
			msg.obj = e.getMessage();
			msg.what = IO_ERROR;
			loginHandler.sendMessage(msg);
		}
	}

	private void saveCredentials(boolean value) {
		if (value) {
			getSharedPreferences(PREFS_NAME, MODE_PRIVATE).edit()
					.putString(PREF_USERNAME, username)
					.putString(PREF_PASSWORD, password)
					.putBoolean(PREF_REMEMBER, true).commit();
		} else {
			getSharedPreferences(PREFS_NAME, MODE_PRIVATE).edit().clear()
					.commit();
		}
	}

	private Object loadCredentials(String key) {
		SharedPreferences pref = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
		if (key.equals(PREF_REMEMBER)) {
			return pref.getBoolean(key, false);
		}
		return pref.getString(key, "");
	}

	private void initPage(String url) throws ConnectException, LoginException,
			IOException {

		cm.getEsse3Connection().get(url);

		String page_HTML = Utils.inputStreamToString(cm.getEsse3Connection()
				.getEntity().getContent());
		if (isMultiID(page_HTML)) {
			selectID(page_HTML);
			return;
		}
		html_pages.put("LIB", page_HTML);
		cm.getEsse3Connection().get(Utils.target_info);
		html_pages.put(
				"INFO",
				Utils.inputStreamToString(cm.getEsse3Connection().getEntity()
						.getContent()));
		html_pages.put(
				"ISCRIZ",
				Utils.inputStreamToString(cm.getSsolConnection().getEntity()
						.getContent()));

		loginHandler.sendEmptyMessage(SUCCESS);
	}

	// ritorna true se l'utente deve scegliere tra più matricole
	private boolean isMultiID(String page_HTML) {
		return page_HTML.contains("Scegli carriera");
	}

	// visualizza un menu con le matricole dell'utente(triennale,
	// specialistica...)
	private void selectID(String page_HTML) {
		iconContextMenu = new IDContextMenu(this, CONTEXT_MENU_ID);
		Resources res = getResources();

		Document jsoupDoc = Jsoup.parse(page_HTML, Utils.target_libretto);
		Elements trs = jsoupDoc.select("table.detail_table").select("tr");
		for (Element tr : trs) {
			Element a = tr.select("td.detail_table>a.detail_table").first();
			if (a != null) {
				String id = a.text();
				String url = Esse3HttpClient.AUTH_URI + a.attr("href");
				iconContextMenu.addItem(res, id, R.drawable.forward_arrow, url);
			}
		}

		iconContextMenu
				.setOnClickListener(new IDContextMenu.IconContextMenuOnClickListener() {

					@Override
					public void onClick(final String url) {
						new Thread(new Runnable() {
							@Override
							public void run() {

								try {
									initPage(url);
								} catch (ConnectException e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
								} catch (LoginException e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
								} catch (IOException e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
								}

							}
						}).start();
					}

				});

		loginHandler.sendEmptyMessage(SHOW_DIALOG);
	}

	// Handler serve per aggiornare la grafica
	private Handler loginHandler = new Handler() {

		@Override
		public void handleMessage(Message msg) {

			switch (msg.what) {
			case SUCCESS:
				intent = new Intent(getApplicationContext(), TabBar.class);
				String pkg = getPackageName();
				// setto i dati ricavati dal login
				intent.putExtra(pkg + ".lib", html_pages.get("LIB"));
				intent.putExtra(pkg + ".info", html_pages.get("INFO"));
				intent.putExtra(pkg + ".iscriz", html_pages.get("ISCRIZ"));
				startActivity(intent);
				progressDialog.dismiss();
				break;
			case CONNECTION_ERROR:
			case LOGIN_ERROR:
			case IO_ERROR:
				builder.setTitle("Login");
				builder.setMessage(msg.obj.toString());
				builder.setIcon(android.R.drawable.ic_dialog_alert);

				builder.setButton("OK", new DialogInterface.OnClickListener() {

					@Override
					public void onClick(DialogInterface dialog, int which) {
						dialog.dismiss();
					}

				});
				progressDialog.dismiss();
				builder.show();
				break;
			case SHOW_DIALOG:
				showDialog(CONTEXT_MENU_ID);
				break;
			default:
				break;
			}
		}
	};

	@Override
	protected Dialog onCreateDialog(int id) {
		if (id == CONTEXT_MENU_ID) {
			return iconContextMenu.createMenu("Scegli matricola");
		}
		return super.onCreateDialog(id);
	}

	@Override
	protected void onResume() {
		super.onResume();
		if (cm != null) {
			cm.reset();
			html_pages.clear();
			Log.i("INFO", "Reset CllientManager!");
		}
	}

	@Override
	public void onClick(View v) {
		if (v == login_B) {
			if (uname.getText().length() == 0) {
				uname.setError("Required");
				return;
			}
			if (pword.getText().length() == 0) {
				pword.setError("Required");
				return;
			}
			progressDialog = ProgressDialog.show(Login.this, "Please wait...",
					"Loading data ...", true);
			new Thread(new Runnable() {
				@Override
				public void run() {
					login();
				}
			}).start();
		}
	}

	private class InputValidator implements TextWatcher {
		private EditText et;

		private InputValidator(EditText editText) {
			this.et = editText;
		}

		@Override
		public void afterTextChanged(Editable s) {

		}

		@Override
		public void beforeTextChanged(CharSequence s, int start, int count,
				int after) {

		}

		@Override
		public void onTextChanged(CharSequence s, int start, int before,
				int count) {
			if (s.length() != 0) {
				switch (et.getId()) {
				case R.id.username:
					if (!Pattern.matches("^[a-z0-9]+$", s)) {
						et.setError("Oops! Prefisso 'id', caratteri accettati a-z e 0-9");
					}

					break;
				}
			}
		}
	}
}